/**
 * 
 */
package com.monkeyboy.mytest.java8.future;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * 
 *
 * @author Gavin<br>
 *         2019年9月26日
 */
public class PriceDemo {

	private List<Shop> shops = Arrays.asList(new Shop("shop1"), new Shop("shop2"), new Shop("shop3"), new Shop("shop4"),
			new Shop("shop5"), new Shop("shop6"), new Shop("shop7"), new Shop("shop8"), new Shop("shop9"),
			new Shop("shop10"), new Shop("shop11"), new Shop("shop12"), new Shop("shop13"), new Shop("shop14"),
			new Shop("shop15"), new Shop("shop16"), new Shop("shop17"));

//	public List<String> findPrices(String product) {
	// 此时需要8秒钟，因为是顺序执行的
//		 return shops.stream().map(shop -> String.format("%s price is%.2f", shop.getName(), shop.getPrice(product)))
//		 .collect(Collectors.toList());
//		}

//	public List<String> findPrices(String product) {
	// 加了parallel()就是并行计算，此时只需要1秒钟就能返回结果，大大提升效率，但是paraller只适用于计算密集型业务，因为它用的线程数量就是cpu的核心数量
//	 return shops.stream().parallel().map(shop -> String.format("%s price is%.2f", shop.getName(), shop.getPrice(product)))
//	 .collect(Collectors.toList());
//	}

	public void findPrices(String product) {

		long start = System.currentTimeMillis();
		//声明线程池
		Executor executor = Executors.newFixedThreadPool(100);

		CompletableFuture<?>[] priceFuture = shops.stream()
				.map(shop -> CompletableFuture.supplyAsync(() -> shop.getPrice(product), executor).thenCombine(
						CompletableFuture.supplyAsync(() -> ExchangeDemo.getRate("USD", "CNY"), executor),
						(quote, rate) -> new Quote(quote.getShop(), quote.getPrice() * rate, quote.getDiscount())))
				.map(future -> future.thenCompose(
						quote -> CompletableFuture.supplyAsync(() -> DiscountDemo.applyDiscount(quote), executor)))
				
				//在每一个完成后都会进行的处理
//				.map(future -> future.thenAccept(content ->  
//				System.out.println(content + " (done in " + (System.currentTimeMillis() - start )+" msecs)")))
				
				.toArray(size -> new CompletableFuture[size]);
//				.collect(Collectors.toList());
		// allOf
		CompletableFuture.anyOf(priceFuture).thenAccept((obj) -> System.out.println("fastest done" + obj));

//		return priceFuture.stream().map(CompletableFuture::join).collect(Collectors.toList());

	}

	public static void main(String[] args) {
//		System.out.println(Runtime.getRuntime().availableProcessors());
		PriceDemo priceDemo = new PriceDemo();
		long start = System.currentTimeMillis();
//		System.out.println(priceDemo.findPrices("iPhone7"));
		priceDemo.findPrices("iPhone7");
		System.out.println("服务耗时:" + (System.currentTimeMillis() - start));
	}

}
